﻿using System;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using MySql.Data.MySqlClient;
using System.Net;
using System.Net.NetworkInformation;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace SystemsAdmin
{
    public class Computer : INotifyPropertyChanged
    {
        [DllImport("iphlpapi.dll", ExactSpelling = true)]
        public static extern int SendARP(int DestIP, int SrcIP, [Out] byte[] pMacAddr, ref int PhyAddrLen);

        public Computer(string mac_address,
            string name,
            string ip_address)
        {
            MACAddress = mac_address;
            Name = name;
            IPAddress = ip_address;
            if (_rdp_template == null)
            {
                LoadRDPTemplate();
            }
        }
        private static string _rdp_template;
        public string MACAddress { get; set; }
        public bool IsON { get; set; }
        public string Name { get; set; }
        private string _ip_address;
        public string IPAddress
        {

            set
            {
                string new_ip_address = value.ToString();
                if (new_ip_address.Contains(".") && new_ip_address != "0.0.0.0")
                {
                    string[] addrs_parts = new_ip_address.Split('.');
                    for (int addrs_idx = 0; addrs_idx < 4; addrs_idx++)
                    {
                        addrs_parts[addrs_idx] = int.Parse(addrs_parts[addrs_idx]).ToString();
                    }
                    _ip_address = String.Join(".", addrs_parts);
                }
            }

            get { return _ip_address; }
        }

        public override String ToString()
        {
            return Name + " " + IPAddress + " " + MACAddress;
        }
        public static List<Computer> GetComputersInDomain(string domainName, string comp_group_name)
        {
            List<Computer> computers_in_domain = new List<Computer>();
            DirectoryEntry de = new DirectoryEntry("WinNT://" + domainName);
            de.Children.SchemaFilter.Add("computer");
            foreach (DirectoryEntry machine in de.Children)
            {
                string[] Ipaddr = new string[3];
                Ipaddr[0] = machine.Name;

                System.Net.IPHostEntry Tempaddr = null;

                try
                {
                    Tempaddr = (System.Net.IPHostEntry)Dns.GetHostEntry(machine.Name);
                }
                catch (Exception ex)
                {
                    continue;
                }
                System.Net.IPAddress[] TempAd = Tempaddr.AddressList;
                IPAddress TempA = TempAd[0];
                Ipaddr[1] = TempA.ToString();

                byte[] ab = new byte[6];
                int len = ab.Length;

                // This Function Used to Get The Physical Address
                int r = SendARP(BitConverter.ToInt32(TempA.GetAddressBytes(), 0), 0, ab, ref len);
                string mac = BitConverter.ToString(ab, 0, 6);

                Computer new_comp = new Computer(mac,
                    machine.Name,
                    TempA.ToString());
                computers_in_domain.Add(new_comp);
                new Thread(new_comp.Refresh).Start();
            }
            return computers_in_domain;
        }
        //public static string GetComputersAttributes(string domainName)
        //{
        //    string attributes = "";
        //    DirectoryEntry de = new DirectoryEntry("LDAP://" + domainName);
        //    //de.Children.SchemaFilter.Add("StaffComputers");
        //    foreach (DirectoryEntry c in de.Children)
        //    {
        //        attributes += "\n " + c.Name;
        //        PropertyCollection computer_properties = c.Properties;
        //        foreach (string prop_name in computer_properties.PropertyNames)
        //        {
        //            attributes += "\n\t - " + prop_name + " = " + computer_properties[prop_name].Value.ToString();
        //        }
        //        //computers_in_doimain.Add(new Computer(c.Properties["macAddress"].Value.ToString(), 
        //        //    c.Name, c.Properties["ipHostNumber"].Value.ToString()));
        //    }
        //    return attributes;
        //}

        public void Refresh()
        {
            Ping pingSender = new Ping();
            try
            {
                PingReply reply = pingSender.Send(IPAddress);
                IsON = (reply.Status == IPStatus.Success);
                OnPropertyChanged("IsON");
            }
            catch (Exception e)
            {
            }

            ////Find out if it is ON
            //string executable = Environment.ExpandEnvironmentVariables(@"%SystemRoot%\system32\ping.exe");
            //string result = ExternalApp.RunReturningOutput(executable, IPAddress);

            //IsON = result.Contains("Lost = 0");

        }

        public void TurnOn()
        {
            WOL.WakeFunction(MACAddress);
        }

        



        public void LoadRDPTemplate()
        {
            StreamReader re = File.OpenText(@"templates\rdp_template.txt");
            _rdp_template = re.ReadToEnd();
            re.Close();
        }

        //Generates a Remote Desktop connection configuration file from a template and return the filename of the template.
        public string GenerateRdpFile()
        {
            //Create the new rdp file
            FileInfo t = new FileInfo(Name + ".rdp");
            StreamWriter Tex = t.CreateText();
            Tex.Write(_rdp_template.Replace("<%= @ip_address_to_view  %>", IPAddress));

            Tex.Close();
            return t.FullName;
        }


        public static string FILES_COPIED_OK_MSG = "Files Copied!";


        // Uses admin shares to copy a file or folder specified by source to 
        //  the destination in the computer
        public string CopyFolder(string source_path, string destination)
        {
            destination = destination.Replace(":", "$");
            var source = new DirectoryInfo(source_path);
            try
            {
                source.CopyTo(@"\\" + IPAddress + @"\" + destination, true);

            }
            catch (Exception e)
            {
                return e.ToString();

            }
            return FILES_COPIED_OK_MSG;
        }
        // Uses admin shares to copy a file or folder specified by source to 
        //  the destination in the computer
        public string CopyFiles(string source, string destination)
        {
            destination = destination.Replace(":", "$");
            //ExternalApp.RunReturningOutput("xcopy", "\"" + source + "\" \"" + destination + "\" /R /I /C /H /K /E /Y");
            try
            {
                System.IO.File.Copy(source, @"\\" + IPAddress + @"\" + destination);

            }
            catch (Exception e)
            {
                return e.ToString();

            }
            return FILES_COPIED_OK_MSG;
        }

        

        #region INotifiedProperty Block
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

    }
}
